package top.pengdev.esoffice.util;

import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.GetAliasesResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.stereotype.Component;
import top.pengdev.esoffice.common.model.Pager;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author pengdev
 * @description
 * @date 2020-11-25 14:15
 **/
@Component
public class EsUtil {

    private static final int DEFAULT_TIMEOUT = 1;
    private static final String DOC = "_doc";

    @Resource
    private RestHighLevelClient client;
    private int timeout;

    /**
     * 创建一个索引
     * @param index
     * @return
     */
    public boolean createIndex(String index){
        if (existsIndex(index)){
            return true;
        }
        try {
            CreateIndexRequest request = new CreateIndexRequest(index);
            CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
            return response.isAcknowledged();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 判断ES索引是否存在
     * @param index
     * @return
     */
    public boolean existsIndex(String index) {
        try{
            GetIndexRequest request = new GetIndexRequest();
            request.indices(index);
            return client.indices().exists(request, RequestOptions.DEFAULT);
        }catch (IOException e){
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 创建文档
     * @param index
     * @param id
     * @param json
     * @return
     */
    public boolean createDoc(String index, String id, String json){
        createIndex(index);
        try {
            IndexRequest request = new IndexRequest(index, DOC, id);
            request.source(json, XContentType.JSON);
            IndexResponse response = client.index(request, RequestOptions.DEFAULT);
            return RestStatus.CREATED.equals(response.status());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     *
     * @param index
     * @param id
     * @return
     */
    public Map<String, Object> getDoc(String index, String id){
        try {
            GetRequest request = new GetRequest(index, DOC, id);
            GetResponse response = client.get(request, RequestOptions.DEFAULT);
            return response.getSource();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    public List<Object> searchIndex(String index, Pager pager, Map<String, String> queries){
        try {
            SearchSourceBuilder builder = new SearchSourceBuilder();

            //条件查询
            BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
            for (Map.Entry<String, String> entry : queries.entrySet()) {
                boolBuilder.must(QueryBuilders.matchQuery(entry.getKey(), entry.getValue()));
            }
            builder.query(boolBuilder);

            //分页
            builder.from(pager.getStartLocation());
            builder.size(pager.getPageSize());
            //设置超时
            builder.timeout(new TimeValue(getTimeout(), TimeUnit.SECONDS));

            SearchRequest request = new SearchRequest();
            request.indices(index);
            request.source(builder);
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            if (response.status() != RestStatus.OK || response.getHits().getTotalHits() <= 0){
                return Collections.emptyList();
            }
            pager.setTotalSize((int) response.getHits().getTotalHits());
            return Arrays.stream(response.getHits().getHits())
                    .map(SearchHit::getSourceAsMap)
                    .collect(Collectors.toList());
        }catch (Exception e){
            e.printStackTrace();
        }
        return Collections.emptyList();
    }

    /**
     * 查询ES所有索引
     * @return
     */
    public Set getIndices() {
        try {
            GetAliasesRequest request = new GetAliasesRequest();
            GetAliasesResponse response = client.indices().getAlias(request, RequestOptions.DEFAULT);
            Map<String, Set<AliasMetaData>> alias = response.getAliases();
            return alias.keySet();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public int getTimeout() {
        return timeout < 0 ? DEFAULT_TIMEOUT : timeout;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }


}
